package com.lyun.controller;

import com.lyun.bo.TodayBestBo;
import com.lyun.common.BaseContext;
import com.lyun.common.EveryConstant;
import com.lyun.common.JwtUtils;
import com.lyun.common.R;
import com.lyun.dto.RecommendationDTO;
import com.lyun.pojo.User;
import com.lyun.service.*;
import com.lyun.vo.PageVO;
import com.lyun.vo.PersonalVo;
import com.lyun.vo.SearchVo;
import com.lyun.vo.TodayBestVO;
import io.jsonwebtoken.Claims;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/tanhua")
@CrossOrigin//跨域支持
public class TanhuaController {

    @DubboReference
    private UserService userService;

    @DubboReference
    private LoveValueService loveValueService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @DubboReference
    private SettingService settingService;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @DubboReference
    private EachLoveService eachLoveService;

    @Resource
    private TanhuaService tanhuaService;

    /**
     * 获取今日佳人
     * @param token
     * @return
     */
    @GetMapping("todayBest")
    public TodayBestVO getTodayBest(@RequestHeader("Authorization") String token) {

        Claims claims = JwtUtils.getClaims(token);
        Long id = ((Integer) claims.get("id")).longValue();

        TodayBestBo bo = new TodayBestBo();
        bo.setId(id);

        return tanhuaService.todayBest(bo);
    }

    /**
     * 13-APP-推荐好友列表（首页）
     * @param dto 推荐好友基本参数
     * @return 包含推荐用户信息的分页结果对象
     */
    @GetMapping("/recommendation")
    public PageVO<TodayBestVO> recommendation(RecommendationDTO dto) {

        //先获取ID
        Long id = BaseContext.getCurrentId();

        // 1性别要不同
        // 2年龄差距 ±5
        // 3教育最好相同
        // 4城市最好相同
        // 5按登录时间排序
        // 6不能是黑名单里的
        return tanhuaService.getRecommendationList(id, dto);
    }

    @GetMapping("/{id}/personalInfo")
    public PersonalVo getPersonalInfo(@RequestHeader(name = "Authorization") String token, @PathVariable("id") Long userId) {

        Claims claims = JwtUtils.getClaims(token);
        long selfId = ((Integer) claims.get("id")).longValue();

        return userService.getPersonalVoByIdAndUserId(selfId, userId);
    }

    @GetMapping("/strangerQuestions")
    public String getQuestions(@RequestParam("userId") Long uid) {
        return settingService.getStrangerQuestionsById(uid);
    }


    /**
     * 17-APP-搜附近
     *
     * @param token
     * @param gender
     * @param distance
     * @return
     */
    @GetMapping("/search")
    public List<SearchVo> searchNearby(@RequestHeader("Authorization") String token, @RequestParam(value = "gender", required = false) String gender, @RequestParam(value = "distance", required = false) Double distance) {

        Claims claims = JwtUtils.getClaims(token);
        String id = claims.get("id").toString();

        List<Point> position = redisTemplate.opsForGeo().position(EveryConstant.REDIS_GEO_USER, id);

        if (CollectionUtils.isEmpty(position) || position.get(0) == null) {
            return null;
        }

        Point point = position.get(0);

        Circle circle = new Circle(point, distance);
        GeoResults<RedisGeoCommands.GeoLocation<Object>> geoResults = redisTemplate.opsForGeo().radius(EveryConstant.REDIS_GEO_USER, circle);

        if (geoResults == null) {
            return null;
        }

        List<Long> ids = new ArrayList<>();

        for (GeoResult<RedisGeoCommands.GeoLocation<Object>> getR : geoResults) {
            String userId = getR.getContent().getName().toString();
            if (userId.equals(id)) {
                continue;
            }
            ids.add(Long.valueOf(userId));
        }

        List<User> listByIds = userService.getListByIds(ids);

        return listByIds.stream().map((user) -> {
            if (!gender.equals(user.getGender())) {
                return null;
            }
            SearchVo searchVo = new SearchVo();
            searchVo.setAvatar(user.getHeader());
            searchVo.setNickname(user.getNickname());
            searchVo.setUserId(user.getId());
            return searchVo;
        }).filter(Objects::nonNull).collect(Collectors.toList());
        /*Distance radius = new Distance(distance, RedisGeoCommands.DistanceUnit.KILOMETERS);
        Circle circle = new Distance(new Point(longitude, latitude), radius);
        GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = redisTemplate.opsForGeo().radius(key, circle);
        List<GeoResult<RedisGeoCommands.GeoLocation<String>>> result = geoResults.getContent();*/
    }

    /**
     * 左滑右滑
     *
     * @return
     */
    @GetMapping("/cards")
    public List<PersonalVo> getCards() {
        Long id = BaseContext.getCurrentId();

        return userService.getRecommendUserList(id);
    }

    @GetMapping("{id}/love")
    public R<String> personalLove(@PathVariable("id") Long toId) {
        Long id = BaseContext.getCurrentId();

        eachLoveService.insertOrUpdate(id, toId);

        return R.success("已添加喜欢" + toId);
    }

    /**
     * 探花界面 不喜欢
     *
     * @param toId 传来的不喜欢的用户的id
     */
    @GetMapping("{id}/unlove")
    public void personalUnLove(@PathVariable("id") Long toId) {
        Long id = BaseContext.getCurrentId();

        eachLoveService.removeBySelfIdAndUserId(id, toId);

        String key = EveryConstant.REDIS_USER_UNLIKE + id.toString() + "to" + toId.toString();

        //将数据存入redis 时效为7天 表示不喜欢该用户
        redisTemplate.opsForValue().set(key, "abc", 7, TimeUnit.DAYS);

    }

}
